<?php

namespace App\Service\Check;

use App\Enums\BaseErrorCode;
use App\Enums\Check\CheckEnum;
use App\Enums\OpenShop\InvestmentPromotion\SignOrderEnum;
use App\Exceptions\Custom\ResponseHttpException;
use App\Library\FeiShu\SendFs;
use App\Library\Rms\RmsPayApi;
use App\Models\Check\CheckCmbBankFlow;
use App\Models\Check\CheckDayOverviewModel;
use App\Models\Check\CheckStreamModel;
use App\Models\Cruise\CruiseCheckAgainstModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopAddressModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopMainProcessModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderPayHistoryModel;
use App\Service\Check\KfDataSource\BaseKfDataSource;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;

class CheckStreamService
{
    private CheckStreamParam $param;

    public function __construct(CheckStreamParam $param)
    {
        $this->param = $param;
    }

    /**
     * 处理对账
     * @return void
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function doCheck(): void
    {
        // 删除数据
        $this->delData();

        // 初始化新增数据
        BaseKfDataSource::classLists()->each(function ($item) {
            (new $item)->setCheckStreamParam($this->param)->addKfDataSource();
        });

        // 下载对账文件
        $checkFiles = $this->getCheckFile();

        // 分析对账文件
        if ($checkFiles) {
            $this->analyseCheckFile($checkFiles);
        }

        // 同步当日数据
        $this->addDayOverview();

        // 计算招商银行流水
        $this->cmbBank();

        // 发送飞书结果
        $this->sendStatCheckFs();
    }

    // 删除当日数据
    private function delData(): void
    {
        $startTime = $this->param->getStartTime();
        $endTime   = $this->param->getEndTime();

        CheckStreamModel::query()
                        ->whereBetween('tradeTime', [$startTime, $endTime])
                        ->delete();

        CheckDayOverviewModel::query()
                             ->whereBetween('date', [(int)date('Ymd', $startTime), (int)date('Ymd', $endTime)])
                             ->delete();
    }

    // 同步当日数据
    private function addDayOverview()
    {
        $timeData = [];

        CheckStreamModel::query()
                        ->whereBetween('tradeTime', [$this->param->getStartTime(), $this->param->getEndTime()])
                        ->chunk(200, function ($streams) use (&$timeData) {
                            $streams->each(function ($item) use (&$timeData) {
                                $cDate = date('Ymd', $item->tradeTime);

                                if (!isset($timeData[$cDate])) {
                                    foreach (CheckDayOverviewModel::TOTAL_COLUMN as $column) {
                                        $timeData[$cDate][$column] = 0;
                                    }
                                    $timeData[$cDate]['date'] = $cDate;
                                }

                                $timeData[$cDate]['totalNum'] += 1;
                                if ($item->checkStatus == CheckEnum::CHECK_STATUS_SUCCESS) {
                                    $timeData[$cDate]['commonNum'] += 1;
                                } elseif ($item->checkStatus == CheckEnum::CHECK_STATUS_AUDIT) {
                                    $timeData[$cDate]['auditNum'] += 1;
                                } elseif ($item->checkStatus == CheckEnum::CHECK_STATUS_ERROR) {
                                    $timeData[$cDate]['errorNum'] += 1;
                                }

                                $timeData[$cDate]['orderPrice']  += $item->orderPrice;
                                $timeData[$cDate]['tradePrice']  += $item->tradePrice;
                                $timeData[$cDate]['incomePrice'] += $item->incomePrice;
                                $timeData[$cDate]['feePrice']    += $item->feePrice;
                            });
                        });

        // 没记录的时候，生成一条空数据
        if (!$timeData) {
            $arr = [];
            foreach (CheckDayOverviewModel::TOTAL_COLUMN as $column) {
                $arr[$column] = 0;
            }
            $arr['date'] = date('Ymd', $this->param->getStartTime());
            $timeData[] = $arr;
        }

        CheckDayOverviewModel::batchAddData(collect($timeData), false);
    }

    /**
     * 交易明细
     * @return array
     */
    public function streamLists(): array
    {
        $query = CheckStreamModel::query()
                                 ->with("signOrderRel")
                                 ->when($this->param->getStartTime(), function ($query) {
                                     $query->where('tradeTime', '>=', $this->param->getStartTime());
                                 })
                                 ->when($this->param->getEndTime(), function ($query) {
                                     $query->where('tradeTime', '<', $this->param->getEndTime());
                                 })
                                 ->when($this->param->getCheckStatus(), function ($query) {
                                     $query->where('checkStatus', $this->param->getCheckStatus());
                                 })
                                 ->when($this->param->getOrderId(), function ($query) {
                                     $query->where('orderId', $this->param->getOrderId());
                                 })
                                 ->when($this->param->getPayNo(), function ($query) {
                                     $query->where('payNo', $this->param->getPayNo());
                                 })
                                 ->when($this->param->getSysTypes(), function ($query) {
                                     $query->whereIn('sysType', $this->param->getSysTypes());
                                 })
                                 ->when($this->param->getPayChannel(), function ($query) {
                                     $query->where('payChannel', $this->param->getPayChannel());
                                 })
                                 ->when($this->param->getPayAction(), function ($query) {
                                     $query->where('payAction', $this->param->getPayAction());
                                 });

        // 分页数据
        $page = (clone $query)->orderByDesc('tradeTime')
                      ->paginate($this->param->getPageSize(), '*', 'page', $this->param->getPageNum());

        // 合计
        $total = $query->selectRaw('sum(orderPrice) as orderPrice, sum(tradePrice) as tradePrice, sum(feePrice) as feePrice, sum(incomePrice) as incomePrice')
                       ->get()
                       ->map(function ($item) {
                           return [
                               'orderPrice'  => (int)$item['orderPrice'],
                               'tradePrice'  => (int)$item['tradePrice'],
                               'feePrice'    => (int)$item['feePrice'],
                               'incomePrice' => (int)$item['incomePrice'],
                           ];
                       })->first();

        $shopCodes = OpenShopSignOrderPayHistoryModel::query()
                                                     ->withoutGlobalScope('isDel')
                                                     ->with('signOrderRel')
                                                     ->with('mainProcessRel')
                                                     ->whereIn('bizId', collect($page->items())->pluck('orderId'))
                                                     ->select('orderNo', 'bizId')
                                                     ->get()
                                                     ->map(function ($item) {
                                                         $item['shopCode'] = $item->signOrderRel->kfShopCode ?? "";

                                                         return $item;
                                                     })
                                                     ->keyBy('bizId');
        $data = [
            'hasMore'  => $page->hasMorePages(),
            'count'    => $page->total(),
            'pageSize' => $this->param->getPageSize(),
            'pageNum'  => $this->param->getPageNum(),
            'total'    => $total,
            'lists'    => collect($page->items())
                ->map(function ($item) use ($shopCodes) {

                    $mainProcessIds = collect();
                    if ($shopCodes[$item->orderId]->mainProcessRel) {
                        $mainProcessIds = OpenShopMainProcessModel::query()
                                                                  ->where('pid', $shopCodes[$item->orderId]->mainProcessRel->pid)
                                                                  ->pluck('id');
                    }

                    $relShopCodes = '';
                    if ($mainProcessIds->count()) {

                        // 多店
                        $shops = OpenShopSignOrderModel::query()
                                                              ->whereIn('mainProcessId', $mainProcessIds)
                                                              ->where('status', '!=', SignOrderEnum::ORDER_STATUS_NO)
                                                              ->pluck('shopCode')
                                                              ->unique();

                        if ($shops->count() > 1) {
                            $relShopCodes = $shops->implode('、');
                        }
                    }

                    return [
                        'tradeAt'         => date('Y-m-d H:i:s', $item->tradeTime),
                        'orderId'         => $item->orderId,
                        'subject'         => $item->subject,
                        'sysType'         => $item->sysType,
                        'sysTypeText'     => $item->sysTypeText,
                        'thirdPayNo'      => $item->thirdPayNo,
                        'companyAccount'  => $item->companyAccount,
                        'payNo'           => $item->payNo,
                        'payChannelText'  => $item->payChannelText,
                        'payActionText'   => $item->payActionText,
                        'tradeStatusText' => '已支付', // TODO
                        'orderPrice'      => $item->orderPrice,
                        'tradePrice'      => $item->tradePrice,
                        'incomePrice'     => $item->incomePrice,
                        'feePrice'        => $item->feePrice,
                        'feeRate'         => ($item->feeRate * 100) . '%',
                        'checkStatus'     => $item->checkStatus,
                        'checkStatusText' => $item->checkStatusText,
                        'errorReason'     => $item->errorReason,
                        'remark'          => $item->remark,
                        'shopCode'        => $shopCodes[$item->orderId]['shopCode'] ?? '',
                        'relShopCodes'    => $relShopCodes,
                        'invalidateType'  => OpenShopSignOrderModel::INVALIDATE_TYPE_TEXT[
                            attributeGet($item,"signOrderRel.invalidateType", 0)
                        ] ?? ""
                    ];
                }),
        ];

        // 列表返回
        if (!$this->param->getExport()) {
            return $data;
        }

        // 导出csv
        $url = $this->streamListsExport($data, $this->param->getExport());

        return ['url' => $url];
    }

    /**
     * 交易明细导出
     * @param array $data
     */
    private function streamListsExport(array $data, int $export)
    {
        ini_set('max_execution_time', 100000);
        header("Content-Disposition: attachment; filename=" . urlencode('开店加盟交易流水对账单') . date('Y-m-d',
                $this->param->getStartTime()) . '.csv');

        // UTF8的BOM头
        if ($export == CheckStreamParam::EXPORT_COMMAND) {
            $filename = "streamListsExport:".time().'.csv';

            // 文件存储的路径
            $filename = sys_get_temp_dir() . '/' . $filename;
        } else {
            $filename = 'php://output';
        }

        $fd = fopen($filename, 'w+');
        fwrite($fd, "\xEF\xBB\xBF");

        // 统计结果
        collect($this->statData(CheckEnum::STAT_TYPE_STREAM))->each(function ($item) use (&$fd) {
            fputcsv($fd, [$item]);
        });
//        ob_flush();
//        flush();

        fputcsv($fd, []);

        // 表头
        fputcsv($fd, [
            '交易时间',
            '门店编号',
            '业务订单编号',
            '订单摘要',
            '订单类型',
            '订单金额',
            '第三方交易单号',
            '收款商户号/收款账户',
            '支付/交易流水号',
            '支付渠道',
            '付款类型',
            '交易状态',
            '交易金额（元）',
            '入账金额（元）',
            '交易手续费（元）',
            '支付费率',
            '对账状态',
            '异常原因',
            '备注',
            '关联店铺号',
            '作废原因'
        ]);
        $data['lists']->each(function ($item) use (&$fd) {
            fputcsv($fd, [
                '`' . $item['tradeAt'],
                $item['shopCode'],
                is_numeric($item['orderId']) ? ('`' . $item['orderId']) : $item['orderId'],
                $item['subject'],
                $item['sysTypeText'],
                bcdiv100($item['orderPrice']),
                '`' . $item['thirdPayNo'],
                '`' . $item['companyAccount'],
                '`' . $item['payNo'],
                $item['payChannelText'],
                $item['payActionText'],
                $item['tradeStatusText'],
                bcdiv100($item['tradePrice']),
                bcdiv100($item['incomePrice']),
                bcdiv100($item['feePrice']),
                $item['feeRate'],
                $item['checkStatusText'],
                $item['errorReason'],
                $item['remark'],
                $item['relShopCodes'],
                $item['invalidateType']
            ]);
//            ob_flush();
//            flush();
        });

        fputcsv($fd, []);

        // 合计
        $total = $data['total'];
        fputcsv($fd, [
            '合计',
            '',
            '',
            '',
            bcdiv100($total['orderPrice']),
            '',
            '',
            '',
            '',
            '',
            '',
            bcdiv100($total['tradePrice']),
            bcdiv100($total['incomePrice']),
            bcdiv100($total['feePrice']),
            '',
            '',
            '',
            '',
        ]);


        if ($export == CheckStreamParam::EXPORT_COMMAND) {
            return $filename;
        } else {

            ob_flush();
            flush();

            if (is_resource($fd)) {
                fclose($fd);
            }

            die;
        }
    }

    /**
     * 每日明细
     * @return array
     */
    public function dayLists(): array
    {
        $lists = CheckDayOverviewModel::query()
                                      ->when($this->param->getStartTime(), function ($query) {
                                          $query->where('date', '>=', (int)date('Ymd', $this->param->getStartTime()));
                                      })
                                      ->when($this->param->getEndTime(), function ($query) {
                                          $query->where('date', '<=', (int)date('Ymd', $this->param->getEndTime()));
                                      })
//                                      ->when($this->param->getSysTypes(), function ($query) {
//                                          $query->whereIn('sysType', $this->param->getSysTypes());
//                                      })
                                      ->select(array_merge(['date'], CheckDayOverviewModel::TOTAL_COLUMN))
                                      ->orderByDesc('date')
                                      ->get()
                                      ->map(function ($item) {
                                          $item['date'] = date('Y-m-d', strtotime($item['date']));
                                          return $item;
                                      });

        // 合计
        $total = [];
        foreach (CheckDayOverviewModel::TOTAL_COLUMN as $column) {
            $total[$column] = 0;
        }

        $lists->each(function ($item) use (&$total) {
            foreach (CheckDayOverviewModel::TOTAL_COLUMN as $column) {
                $total[$column] += $item[$column];
            }
        });

        $data = [
            'count' => $lists->count(),
            'lists' => $lists,
            'total' => $total,
        ];

        // 列表返回
        if (!$this->param->getExport()) {
            return $data;
        }

        // 导出csv
        $this->dayListsExport($data);

        return [];
    }

    /**
     * 每日明细导出
     * @return void
     */
    private function dayListsExport(array $data): void
    {
        ini_set('max_execution_time', 100000);
        header("Content-Disposition: attachment; filename=" . urlencode('开店加盟对账单') . date('Y-m-d',
                $this->param->getStartTime()) . '-' . date('Y-m-d', $this->param->getEndTime()) . '.csv');

        // UTF8的BOM头
        $fd = fopen('php://output', 'w+');
        fwrite($fd, "\xEF\xBB\xBF");

        // 统计结果
        collect($this->statData(CheckEnum::STAT_TYPE_DAY))->each(function ($item) use (&$fd) {
            fputcsv($fd, [$item]);
        });
        ob_flush();
        flush();

        fputcsv($fd, []);

        // 表头
        fputcsv($fd, [
            '交易时间',
            '订单合计',
            '正常订单',
            '异常订单',
            '待审核订单',
            '订单金额',
            '交易金额（元）',
            '入账金额（元）',
            '交易手续费（元）',
        ]);
        $data['lists']->each(function ($item) use (&$fd) {
            fputcsv($fd, [
                date('Y-m-d', strtotime($item['date'])),
                $item['totalNum'],
                $item['commonNum'],
                $item['errorNum'],
                $item['auditNum'],
                bcdiv100($item['orderPrice']),
                bcdiv100($item['tradePrice']),
                bcdiv100($item['incomePrice']),
                bcdiv100($item['feePrice']),
            ]);
            ob_flush();
            flush();
        });

        fputcsv($fd, []);

        // 合计
        $total = $data['total'];
        fputcsv($fd, [
            '合计',
            $total['totalNum'],
            $total['commonNum'],
            $total['errorNum'],
            $total['auditNum'],
            bcdiv100($total['orderPrice']),
            bcdiv100($total['tradePrice']),
            bcdiv100($total['incomePrice']),
            bcdiv100($total['feePrice'])
        ]);
        ob_flush();
        flush();

        if (is_resource($fd)) {
            fclose($fd);
        }
        die;
    }

    // TODO 晚点把sql优化下
    private function statData(int $statType): array
    {
        if ($statType == CheckEnum::STAT_TYPE_STREAM) {
            $obj = CheckStreamModel::query()
                                   ->whereBetween('tradeTime',
                                       [$this->param->getStartTime(), $this->param->getEndTime()]);

            $orderCount    = $obj->count();
            $orderPriceSum = $obj->sum('orderPrice');
            $tradePriceSum = $obj->sum('tradePrice');
            $incomeSum     = $obj->sum('incomePrice');
            $feeSum        = $obj->sum('feePrice');

            $commonCount = (clone $obj)->where('checkStatus', CheckEnum::CHECK_STATUS_SUCCESS)->count();
            $errCount    = (clone $obj)->where('checkStatus', CheckEnum::CHECK_STATUS_ERROR)->count();
            $startAt     = date('Y-m-d H:i:s', $this->param->getStartTime());
            $endAt       = date('Y-m-d H:i:s', $this->param->getEndTime());
        } elseif ($statType == CheckEnum::STAT_TYPE_DAY) {
            $obj = CheckDayOverviewModel::query()
                                        ->whereBetween('date', [
                                            date('Ymd', $this->param->getStartTime()),
                                            date('Ymd', $this->param->getEndTime())
                                        ]);

            $orderCount    = (int)$obj->sum('totalNum');
            $orderPriceSum = $obj->sum('orderPrice');
            $tradePriceSum = $obj->sum('tradePrice');
            $incomeSum     = $obj->sum('incomePrice');
            $feeSum        = $obj->sum('feePrice');

            $commonCount = (int)$obj->sum('commonNum');
            $errCount    = (int)$obj->sum('errorNum');
            $startAt     = date('Y-m-d', $this->param->getStartTime());
            $endAt       = date('Y-m-d', $this->param->getEndTime());
        } else {
            throw new ResponseHttpException(BaseErrorCode::$STAT_TYPE_ERR);
        }

        return [
            sprintf("#起始日期：%s 终止日期：%s", $startAt, $endAt),
            sprintf("#订单金额合计：%d笔，共%s元", $orderCount, bcdiv100($orderPriceSum)),
            sprintf("#交易金额合计：%d笔，共%s元", $orderCount, bcdiv100($tradePriceSum)),
            sprintf("#入账金额合计：%d笔，共%s元", $orderCount, bcdiv100($incomeSum)),
            sprintf("#手续费金额合计：%d笔，共%s元", $orderCount, bcdiv100($feeSum)),
            sprintf("#正常订单合计：%d笔", $commonCount),
            sprintf("#异常订单合计：%d笔", $errCount),
            sprintf("#生成时间：%s", date('Y-m-d H:i:s')),
        ];
    }

    /**
     * 飞书推送对账信息
     * @return void
     */
    private function sendStatCheckFs(): void
    {
        $checkData = $this->statData(CheckEnum::STAT_TYPE_DAY);

        $content = '';
        foreach ($checkData as $text) {
            $content .= $text . PHP_EOL;
        }

        SendFs::newRobot(SendFs::ROBOT_CHECK)->setTitleContent('订单对账结果', $content)->send();
    }

    /**
     * 获取对账文件
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    private function getCheckFile(): array
    {
        $date = (int)date('Ymd', $this->param->getStartTime());

        return (new RmsPayApi(null))->getCheckFileUrl($date)['data']['lists'] ?? [];
    }

    /**
     * 解析对账文件，并对账
     * @return void
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    private function analyseCheckFile(array $checkFiles)
    {
        /*
         * [
              [
                "payChannel" => 1
                "company" => 1
                "date" => 20220412
                "url" => "https://file.51kuafu.com/ef/c1/ab2302f2dbeb2c1a17bd87f5675c098878e3c07504654147d479b065dd44.csv"
              ]
            ]
         * */

        $date = (int)date('Ymd', $this->param->getStartTime());

        foreach ($checkFiles as $checkFile) {
            $fileName = $checkFile['url'];

            $checkLists = [];

            $file = fopen($fileName, 'r');
            while (!feof($file)) {
                $text = fgetcsv($file);
                if (is_array($text)) {

                    print_r($text);

                    if ($checkFile['payChannel'] == CheckEnum::PAY_CHANNEL_ALI) {

                        foreach ($text as &$t) {
                            try {
                                $t = iconv('gb2312', 'utf-8', $t);
                            } catch (\Exception $e) {
                                Log::warning($e);
                            }
                        }

                        // TODO 先这么判断
                        if (count($text) == 25) {
                            $bizType = trim($text[2]);
                            $payNo   = trim($text[1]);
                            if ($bizType == '交易') {
                                $checkLists[$payNo] = $text;
                            }
                        }
                    } elseif ($checkFile['payChannel'] == CheckEnum::PAY_CHANNEL_WX) {
                        foreach ($text as &$t) {
                            $t = trim($t, '`');
                        }

                        if (count($text) == 11) {
                            $bizType = trim($text[4]);
                            $payNo   = trim($text[10]);
                            if ($bizType == '交易') {
                                $checkLists[$payNo] = $text;
                            }
                        }
                    }
                }
            }

            fclose($file);

            // 查短款
            // TODO 后面要改成只查成功的
            CheckStreamModel::query()
                            ->where('payChannel', $checkFile['payChannel'])
                            ->whereBetween('tradeTime', [strtotime($date), strtotime($date) + 86400 - 1])
                            ->chunk(500, function ($streams) use ($checkLists) {
                                $streams->each(function ($item) use ($checkLists) {
                                    $checklistItem = $checkLists[$item['payNo']] ?? [];
                                    if (!$checklistItem) {
                                        return;
                                    }

                                    if ($item['payChannel'] == CheckEnum::PAY_CHANNEL_ALI) {
                                        // 支付宝的逻辑
                                        /**
                                         * Array
                                         * (
                                         * [0] => 支付宝交易号
                                         * [1] => 商户订单号
                                         * [2] => 业务类型
                                         * [3] => 商品名称
                                         * [4] => 创建时间
                                         * [5] => 完成时间
                                         * [6] => 门店编号
                                         * [7] => 门店名称
                                         * [8] => 操作员
                                         * [9] => 终端号
                                         * [10] => 对方账户
                                         * [11] => 订单金额（元）
                                         * [12] => 商家实收（元）
                                         * [13] => 支付宝红包（元）
                                         * [14] => 集分宝（元）
                                         * [15] => 支付宝优惠（元）
                                         * [16] => 商家优惠（元）
                                         * [17] => 券核销金额（元）
                                         * [18] => 券名称
                                         * [19] => 商家红包消费金额（元）
                                         * [20] => 卡消费金额（元）
                                         * [21] => 退款批次号/请求号
                                         * [22] => 服务费（元）
                                         * [23] => 分润（元）
                                         * [24] => 备注
                                         * )
                                         */
                                        $payNo       = $checklistItem[1];
                                        $tradeTime   = strtotime($checklistItem[4]);
                                        $orderPrice  = (int)bcmul($checklistItem[11], 100);
                                        $incomePrice = (int)bcmul($checklistItem[12], 100);
                                        $feePrice    = abs((int)bcmul($checklistItem[22], 100));
                                        $remark      = $checklistItem[24];
                                    } elseif ($item['payChannel'] == CheckEnum::PAY_CHANNEL_WX) {
                                        /*
                                         array (
                                          0 => '记账时间',
                                          1 => '微信支付业务单号',
                                          2 => '资金流水单号',
                                          3 => '业务名称',
                                          4 => '业务类型',
                                          5 => '收支类型',
                                          6 => '收支金额(元)',
                                          7 => '账户结余(元)',
                                          8 => '资金变更提交申请人',
                                          9 => '备注',
                                          10 => '业务凭证号',
                                        )
                                        (
                                        [0] => 2022-04-11 14:49:26
                                        [1] => 4200001353202204115374293027
                                        [2] => 4200001353202204115374293027
                                        [3] => 交易
                                        [4] => 交易
                                        [5] => 收入
                                        [6] => 6150.40
                                        [7] => 672803.15
                                        [8] => system
                                        [9] => 结算总金额 6150.40 元;含手续费 36.90 元
                                        [10] => 202204111449172291611678
                                    )
                                         * */
                                        $payNo      = $checklistItem[10];
                                        $tradeTime  = strtotime($checklistItem[0]);
                                        $orderPrice = (int)bcmul($checklistItem[6], 100);
//                                        $feePrice = $checklistItem[9]; // TODO 需要正则 结算总金额 6150.40 元;含手续费 36.90 元
                                        $feePrice    = (int)bcmul(rtrim(explode('手续费 ', $checklistItem[9])[1], ' 元'),
                                            100);
                                        $incomePrice = $orderPrice - $feePrice;
                                        $remark      = '';
                                    }

                                    $errorMsg = '';

                                    if ($checklistItem) {

                                        if ($orderPrice != $item->orderPrice) {
                                            $errorMsg .= "订单金额错误，三方：{$orderPrice} 己方: {$item->orderPrice}" . PHP_EOL;
                                        }

//                                        if ($incomePrice != $item->incomePrice) {
//                                            $errorMsg .= "收入错误，三方：{$incomePrice} 己方: {$item->incomePrice}" . PHP_EOL;
//                                        }

                                        if ($feePrice != $item->feePrice) {
                                            $errorMsg .= "手续费错误，三方：{$feePrice} 己方: {$item->feePrice}" . PHP_EOL;
                                        }

                                        if (!$errorMsg) {

                                            // 对账成功
                                            $item->checkSuccess();
                                        }

                                    } else {

                                        // 短款
                                        $errorMsg .= "短款";
                                    }

                                    // 更新异常记录
                                    if ($errorMsg) {
                                        $item->checkError($errorMsg);
                                    }
                                });
                            });
        }
    }

    private function cmbBank()
    {
        $query = CheckStreamModel::query()
            ->whereBetween('tradeTime', [
                $this->param->getStartTime(),
                $this->param->getEndTime(),
            ])
            ->where('payChannel', CheckEnum::PAY_CHANNEL_BANK)
            ->where('checkStatus', CheckEnum::CHECK_STATUS_INIT);
        (clone $query)
            ->orderBy('id', 'asc')
            ->get()
            ->map(function ($stream) use ($query) {
                // 看看今天是否有相同金额的其他未对账流水
                $count = CheckStreamModel::query()
                    ->whereBetween('tradeTime', [
                        Carbon::createFromTimestamp($stream->tradeTime)->startOfDay()->timestamp,
                        Carbon::createFromTimestamp($stream->tradeTime)->endOfDay()->timestamp,
                    ])
                    ->where('payChannel', CheckEnum::PAY_CHANNEL_BANK)
                    ->where('orderPrice', $stream->orderPrice)
                    ->whereIn('checkStatus', [CheckEnum::CHECK_STATUS_INIT, CheckEnum::CHECK_STATUS_ERROR])
                    ->whereNotIn('id', [$stream->id])
                    ->count();
                if ($count) {
                    $stream->checkStatus = CheckEnum::CHECK_STATUS_ERROR;
                    $stream->errorReason = '今日未对账开店/筹备订单有多笔相同金额';
                    $stream->save();
                    return;
                }
                // 看看有没有匹配的招商银行订单
                $flows = CheckCmbBankFlow::query()
                    ->whereBetween('etyDateTime', [
                        Carbon::createFromTimestamp($stream->tradeTime)->startOfDay()->toDateTimeString(),
                        Carbon::createFromTimestamp($stream->tradeTime)->endOfDay()->toDateTimeString(),
                    ])
                    ->where('used', 0)
                    ->where('trsblv', $stream->orderPrice / 100)
                    ->get();
                if (!count($flows)) {
                    $stream->checkStatus = CheckEnum::CHECK_STATUS_ERROR;
                    $stream->errorReason = '今日未对账银行类流水没有相同金额';
                    $stream->save();
                    return;
                }
                if (count($flows) > 1) {
                    $stream->checkStatus = CheckEnum::CHECK_STATUS_ERROR;
                    $stream->errorReason = '今日未对账银行类流水没有相同金额';
                    $stream->save();
                    return;
                }
                $flow = $flows->first();
                $flow->used = 1;
                $flow->save();
                $stream->checkStatus = CheckEnum::CHECK_STATUS_SUCCESS;
                $stream->save();
            });
    }
}
